package com.minimalist.common.entity.lindi.vo.contracttemplatefield;

import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.minimalist.common.config.swagger.SchemaEnum;
import com.minimalist.common.entity.lindi.enums.LindiContractTemplateFieldEnum;
import com.minimalist.common.entity.lindi.vo.contracttemplatefieldoption.LindiContractTemplateFieldOptionVO;
import com.minimalist.common.utils.Add;
import com.minimalist.common.utils.Update;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 林地指标平台_合同模板字段配置VO
 * <p>
 * 用于管理合同模板中的字段配置信息，包括字段基本属性、
 * 位置坐标、验证规则、选项配置等功能
 *
 * @author 11987
 * @since 2025-05-31
 */
@Schema(name = "林地指标平台_合同模板字段配置实体")
public class LindiContractTemplateFieldVO implements Serializable {
    
    @Serial
    private static final long serialVersionUID = 1L;

    // ========== 主要业务字段 ==========
    
    /**
     * 合同模板字段配置ID
     */
    @NotNull(message = "合同模板字段配置ID不能为空", groups = {Update.class})
    @JsonSerialize(using = ToStringSerializer.class)
    @Schema(name = "contractTemplateFieldId", description = "合同模板字段配置ID", type = "string")
    private Long contractTemplateFieldId;

    /**
     * 合同模板ID
     */
    @NotNull(message = "合同模板ID不能为空", groups = {Add.class, Update.class})
    @JsonSerialize(using = ToStringSerializer.class)
    @Schema(name = "contractTemplateId", description = "合同模板ID", type = "string")
    private Long contractTemplateId;

    /**
     * 字段名称
     */
    @NotBlank(message = "字段名称不能为空", groups = {Add.class, Update.class})
    @Schema(name = "fieldName", description = "字段名称", type = "string")
    private String fieldName;

    /**
     * 字段标识
     */
    @NotBlank(message = "字段标识不能为空", groups = {Add.class, Update.class})
    @Schema(name = "fieldKey", description = "字段标识", type = "string")
    private String fieldKey;

    /**
     * 字段类型
     */
    @SchemaEnum(implementation = LindiContractTemplateFieldEnum.FieldTypeEnum.class)
    @NotBlank(message = "字段类型不能为空", groups = {Add.class, Update.class})
    @Schema(name = "fieldType", description = "字段类型", type = "string")
    private String fieldType;

    /**
     * 是否必填 0:选填, 1:必填
     */
    @SchemaEnum(implementation = LindiContractTemplateFieldEnum.RequireEnum.class)
    @Schema(name = "fieldRequire", description = "是否必填(0:选填, 1:必填)", type = "integer")
    private Byte fieldRequire;

    // ========== 位置和布局字段 ==========
    
    /**
     * 页码
     */
    @Schema(name = "pageNumber", description = "页码", type = "integer")
    private Integer pageNumber;

    /**
     * X坐标
     */
    @Schema(name = "positionX", description = "X坐标", type = "string")
    private String positionX;

    /**
     * Y坐标
     */
    @Schema(name = "positionY", description = "Y坐标", type = "string")
    private String positionY;

    /**
     * 排序序号
     */
    @Schema(name = "sortOrder", description = "排序序号", type = "string")
    private String sortOrder;

    // ========== 配置字段 ==========
    
    /**
     * 默认值
     */
    @Schema(name = "defaultValue", description = "默认值", type = "string")
    private String defaultValue;

    /**
     * 文本域名称
     */
    @Schema(name = "textFieldName", description = "文本域名称", type = "string")
    private String textFieldName;

    /**
     * 字段选项列表
     */
    @Schema(name = "options", description = "字段选项列表")
    private List<LindiContractTemplateFieldOptionVO> options;

    // ========== 审计字段 ==========
    
    /**
     * 创建人ID
     */
    @JsonSerialize(using = ToStringSerializer.class)
    @Schema(name = "createId", description = "创建人ID", type = "string")
    private Long createId;

    /**
     * 更新人ID
     */
    @JsonSerialize(using = ToStringSerializer.class)
    @Schema(name = "updateId", description = "更新人ID", type = "string")
    private Long updateId;

    /**
     * 创建时间
     */
    @Schema(name = "createTime", description = "创建时间", type = "string")
    @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    @Schema(name = "updateTime", description = "更新时间", type = "string")
    @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
    private LocalDateTime updateTime;

    // ========== 构造函数 ==========
    
    /**
     * 默认构造函数
     */
    public LindiContractTemplateFieldVO() {
    }

    /**
     * 全参数构造函数
     *
     * @param contractTemplateFieldId 合同模板字段配置ID
     * @param contractTemplateId      合同模板ID
     * @param fieldName               字段名称
     * @param fieldKey                字段标识
     * @param fieldType               字段类型
     * @param fieldRequire            是否必填
     * @param pageNumber              页码
     * @param positionX               X坐标
     * @param positionY               Y坐标
     * @param sortOrder               排序序号
     * @param defaultValue            默认值
     * @param textFieldName           文本域名称
     * @param options                 字段选项列表
     * @param createId                创建人ID
     * @param updateId                更新人ID
     * @param createTime              创建时间
     * @param updateTime              更新时间
     */
    public LindiContractTemplateFieldVO(Long contractTemplateFieldId, Long contractTemplateId, String fieldName,
                                       String fieldKey, String fieldType, Byte fieldRequire, Integer pageNumber,
                                       String positionX, String positionY, String sortOrder, String defaultValue,
                                       String textFieldName, List<LindiContractTemplateFieldOptionVO> options,
                                       Long createId, Long updateId, LocalDateTime createTime, LocalDateTime updateTime) {
        this.contractTemplateFieldId = contractTemplateFieldId;
        this.contractTemplateId = contractTemplateId;
        this.fieldName = fieldName;
        this.fieldKey = fieldKey;
        this.fieldType = fieldType;
        this.fieldRequire = fieldRequire;
        this.pageNumber = pageNumber;
        this.positionX = positionX;
        this.positionY = positionY;
        this.sortOrder = sortOrder;
        this.defaultValue = defaultValue;
        this.textFieldName = textFieldName;
        this.options = options;
        this.createId = createId;
        this.updateId = updateId;
        this.createTime = createTime;
        this.updateTime = updateTime;
    }

    /**
     * 基本信息构造函数
     *
     * @param contractTemplateId 合同模板ID
     * @param fieldName          字段名称
     * @param fieldKey           字段标识
     * @param fieldType          字段类型
     */
    public LindiContractTemplateFieldVO(Long contractTemplateId, String fieldName, String fieldKey, String fieldType) {
        this.contractTemplateId = contractTemplateId;
        this.fieldName = fieldName;
        this.fieldKey = fieldKey;
        this.fieldType = fieldType;
        this.fieldRequire = (byte) 0; // 默认选填
    }

    // ========== Getter 和 Setter 方法 ==========
    
    public Long getContractTemplateFieldId() {
        return contractTemplateFieldId;
    }

    public void setContractTemplateFieldId(Long contractTemplateFieldId) {
        this.contractTemplateFieldId = contractTemplateFieldId;
    }

    public Long getContractTemplateId() {
        return contractTemplateId;
    }

    public void setContractTemplateId(Long contractTemplateId) {
        this.contractTemplateId = contractTemplateId;
    }

    public String getFieldName() {
        return fieldName;
    }

    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public String getFieldKey() {
        return fieldKey;
    }

    public void setFieldKey(String fieldKey) {
        this.fieldKey = fieldKey;
    }

    public String getFieldType() {
        return fieldType;
    }

    public void setFieldType(String fieldType) {
        this.fieldType = fieldType;
    }

    public Byte getFieldRequire() {
        return fieldRequire;
    }

    public void setFieldRequire(Byte fieldRequire) {
        this.fieldRequire = fieldRequire;
    }

    public Integer getPageNumber() {
        return pageNumber;
    }

    public void setPageNumber(Integer pageNumber) {
        this.pageNumber = pageNumber;
    }

    public String getPositionX() {
        return positionX;
    }

    public void setPositionX(String positionX) {
        this.positionX = positionX;
    }

    public String getPositionY() {
        return positionY;
    }

    public void setPositionY(String positionY) {
        this.positionY = positionY;
    }

    public String getSortOrder() {
        return sortOrder;
    }

    public void setSortOrder(String sortOrder) {
        this.sortOrder = sortOrder;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }

    public String getTextFieldName() {
        return textFieldName;
    }

    public void setTextFieldName(String textFieldName) {
        this.textFieldName = textFieldName;
    }

    public List<LindiContractTemplateFieldOptionVO> getOptions() {
        return options;
    }

    public void setOptions(List<LindiContractTemplateFieldOptionVO> options) {
        this.options = options;
    }

    public Long getCreateId() {
        return createId;
    }

    public void setCreateId(Long createId) {
        this.createId = createId;
    }

    public Long getUpdateId() {
        return updateId;
    }

    public void setUpdateId(Long updateId) {
        this.updateId = updateId;
    }

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public LocalDateTime getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(LocalDateTime updateTime) {
        this.updateTime = updateTime;
    }

    // ========== Object 方法重写 ==========
    
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        
        LindiContractTemplateFieldVO that = (LindiContractTemplateFieldVO) o;
        
        return Objects.equals(contractTemplateFieldId, that.contractTemplateFieldId) &&
               Objects.equals(contractTemplateId, that.contractTemplateId) &&
               Objects.equals(fieldName, that.fieldName) &&
               Objects.equals(fieldKey, that.fieldKey) &&
               Objects.equals(fieldType, that.fieldType) &&
               Objects.equals(fieldRequire, that.fieldRequire) &&
               Objects.equals(pageNumber, that.pageNumber) &&
               Objects.equals(positionX, that.positionX) &&
               Objects.equals(positionY, that.positionY) &&
               Objects.equals(sortOrder, that.sortOrder) &&
               Objects.equals(defaultValue, that.defaultValue) &&
               Objects.equals(textFieldName, that.textFieldName) &&
               Objects.equals(options, that.options) &&
               Objects.equals(createId, that.createId) &&
               Objects.equals(updateId, that.updateId) &&
               Objects.equals(createTime, that.createTime) &&
               Objects.equals(updateTime, that.updateTime);
    }

    @Override
    public int hashCode() {
        return Objects.hash(contractTemplateFieldId, contractTemplateId, fieldName, fieldKey, fieldType,
                           fieldRequire, pageNumber, positionX, positionY, sortOrder, defaultValue,
                           textFieldName, options, createId, updateId, createTime, updateTime);
    }

    @Override
    public String toString() {
        return "LindiContractTemplateFieldVO{" +
               "contractTemplateFieldId=" + contractTemplateFieldId +
               ", contractTemplateId=" + contractTemplateId +
               ", fieldName='" + fieldName + '\'' +
               ", fieldKey='" + fieldKey + '\'' +
               ", fieldType='" + fieldType + '\'' +
               ", fieldRequire=" + fieldRequire +
               ", pageNumber=" + pageNumber +
               ", positionX='" + positionX + '\'' +
               ", positionY='" + positionY + '\'' +
               ", sortOrder='" + sortOrder + '\'' +
               ", defaultValue='" + defaultValue + '\'' +
               ", textFieldName='" + textFieldName + '\'' +
               ", options=" + options +
               ", createId=" + createId +
               ", updateId=" + updateId +
               ", createTime=" + createTime +
               ", updateTime=" + updateTime +
               '}';
    }

    // ========== 便利方法 ==========
    
    /**
     * 检查字段是否必填
     *
     * @return true如果字段必填，否则false
     */
    public boolean isRequired() {
        return Byte.valueOf((byte) 1).equals(this.fieldRequire);
    }

    /**
     * 检查字段是否选填
     *
     * @return true如果字段选填，否则false
     */
    public boolean isOptional() {
        return Byte.valueOf((byte) 0).equals(this.fieldRequire);
    }

    /**
     * 设置字段为必填
     */
    public void setRequired() {
        this.fieldRequire = (byte) 1;
    }

    /**
     * 设置字段为选填
     */
    public void setOptional() {
        this.fieldRequire = (byte) 0;
    }

    /**
     * 检查是否有默认值
     *
     * @return true如果有默认值，否则false
     */
    public boolean hasDefaultValue() {
        return defaultValue != null && !defaultValue.trim().isEmpty();
    }

    /**
     * 检查是否有选项配置
     *
     * @return true如果有选项配置，否则false
     */
    public boolean hasOptions() {
        return options != null && !options.isEmpty();
    }

    /**
     * 检查是否有位置坐标
     *
     * @return true如果有位置坐标，否则false
     */
    public boolean hasPosition() {
        return (positionX != null && !positionX.trim().isEmpty()) &&
               (positionY != null && !positionY.trim().isEmpty());
    }
}
